package com.emperor.product.app;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.emperor.cashier.app.CashierAppCtrl;
import com.emperor.category.logic.Category;
import com.emperor.category.logic.CategoryModel;
import com.emperor.core.app.App;
import com.emperor.core.app.AppBase;
import com.emperor.core.app.AppConstant;
import com.emperor.employee.logic.Employee;
import com.emperor.inventory.app.InventoryAppCtrl;
import com.emperor.product.logic.Product;
import com.emperor.product.logic.ProductModel;
import com.emperor.productlog.logic.ProductLog;
import com.emperor.productlog.logic.ProductLogModel;
import com.emperor.transaction.logic.Transaction;
import com.emperor.user.logic.User;
import com.emperor.util.HibernateUtil;
import com.swtdesigner.SWTResourceManager;

public class ProductAppNew extends AppBase implements App {

	private Label categoryLabel_1_3;
	private Label categoryLabel_1_2;
	private Text text_10;
	private Text text_9;
	private Label categoryLabel_1_1;
	private Text text_8;
	private Combo combo_1;
	private Text text_7;
	private Combo combo;
	private Text text_6;
	private Text text_5;
	private Text text_4;
	private Text text_3;
	private Text text_2;
	private Text text;
	protected Shell shell;

	public static Logger log = Logger.getLogger(ProductAppNew.class);

	public ProductAppNew() {
		super();
	}

	public ProductAppNew(Map<String, Object> params) {
		super();
		this.params = params;
	}

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			ProductAppNew window = new ProductAppNew();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setBackgroundImage(SWTResourceManager.getImage(
				ProductAppNew.class, "/img/main.jpg"));
		shell.setImage(SWTResourceManager.getImage(ProductAppNew.class,
				"/img/iMac OSX.png"));
		shell.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
		shell.setSize(1280, 800);
		shell.setText("New Product");

		initScreen(shell, getParams());

		final Composite composite = new Composite(shell, SWT.NONE);
		composite.setBounds(0, 50, 992, 544);

		final Label messageLabel = new Label(composite, SWT.NONE);
		messageLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		messageLabel
				.setText("Please key in the New Product Form below and click Save to add New Product");
		messageLabel.setBounds(10, 0, 550, 20);

		final Label label = new Label(composite, SWT.NONE);
		label.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI",
				12, SWT.NORMAL));
		label.setText("Category");
		label.setBounds(10, 74, 65, 23);

		final Label categoryLabel = new Label(composite, SWT.NONE);
		categoryLabel.setBounds(10, 115, 65, 20);
		categoryLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		categoryLabel.setText("Name");

		final Label categoryLabel_1 = new Label(composite, SWT.NONE);
		categoryLabel_1.setBounds(10, 150, 65, 20);
		categoryLabel_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		categoryLabel_1.setText("SKU");

		final Label categoryLabel_2 = new Label(composite, SWT.NONE);
		categoryLabel_2.setBounds(10, 403, 80, 20);
		categoryLabel_2.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		categoryLabel_2.setText("Description");

		final Label categoryLabel_3 = new Label(composite, SWT.NONE);
		categoryLabel_3.setBounds(10, 293, 35, 20);
		categoryLabel_3.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		categoryLabel_3.setText("Price");

		final Label categoryLabel_4 = new Label(composite, SWT.NONE);
		categoryLabel_4.setBounds(10, 329, 65, 20);
		categoryLabel_4.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		categoryLabel_4.setText("Discount");

		final Label categoryLabel_5 = new Label(composite, SWT.NONE);
		categoryLabel_5.setBounds(10, 365, 65, 20);
		categoryLabel_5.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		categoryLabel_5.setText("Quantity");

		text = new Text(composite, SWT.BORDER);
		text.setToolTipText("prod_name");
		text.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI",
				12, SWT.NORMAL));
		text.setBounds(129, 112, 477, 30);

		text_2 = new Text(composite, SWT.BORDER);
		text_2.setToolTipText("prod_sku");
		text_2.setBounds(129, 147, 477, 30);
		text_2.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		text_3 = new Text(composite, SWT.BORDER);
		text_3.setToolTipText("prod_price");
		text_3.setBounds(129, 290, 172, 30);
		text_3.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		text_4 = new Text(composite, SWT.BORDER);
		text_4.setToolTipText("prod_discount");
		text_4.setBounds(129, 326, 172, 30);
		text_4.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		text_5 = new Text(composite, SWT.BORDER);
		text_5.setToolTipText("prod_quantity");
		text_5.setBounds(129, 362, 172, 30);
		text_5.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		text_6 = new Text(composite, SWT.WRAP | SWT.V_SCROLL | SWT.MULTI
				| SWT.BORDER);
		text_6.setToolTipText("prod_desc");
		text_6.setBounds(129, 400, 477, 129);
		text_6.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		combo = new Combo(composite, SWT.NONE);
		combo.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI",
				12, SWT.NORMAL));
		combo.setBounds(129, 74, 477, 28);

		final Button saveButton = new Button(shell, SWT.NONE);
		saveButton.setImage(SWTResourceManager.getImage(ProductAppNew.class,
				"/img/Save.png"));
		saveButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				try {
					if (combo.getText() != null && combo.getText().length() > 0) {
						Product product = new ProductModel();

						Session session = HibernateUtil.getSessionFactory()
								.getCurrentSession();
						session.beginTransaction();

						Category category = new CategoryModel();
						List<Category> categories = session
								.createCriteria(CategoryModel.class)
								.add(Expression.eq(Category.FLD_NAME,
										combo.getText())).list();
						if (categories != null && !categories.isEmpty()) {
							category = categories.get(0);
						}

						product = (Product) setModel(composite, "prod", product);
						product.setCategory(category);
						log.debug(product.getClass().getSimpleName() + " : "
								+ product.getValues().toString());

						List<String> errors = validateForm(product);
						if (errors.isEmpty()) {
							product = (Product) preAdd(product, getParams());

							product.setStatus(AppConstant.STATUS_ACTIVE);

							int rowCount = doAdd(product);

							if (rowCount == 1) {
								logProduct(product, getParams(),
										ProductLog.ACT_STOCK_IN + "-"
												+ ProductLog.ACT_NEW, null,
										null);

								message(getShell(), "Save Success.",
										"Product added successfully.");

								getParams().put(AppConstant.APPCTRL,
										InventoryAppCtrl.INVENTORY_CTRL);
								getParams().put(AppConstant.ACTION,
										InventoryAppCtrl.INVENTORY_ENQ);
								getShell().close();
							} else {
								message(getShell(), "Save Error.",
										"Unable to add product.",
										SWT.ICON_ERROR | SWT.OK);
							}
						} else {
							message(getShell(), "Save Error", errors,
									SWT.ICON_ERROR | SWT.OK);
						}
					} else {
						message(getShell(), "Save Error.",
								"Please select a category.", SWT.ICON_ERROR
										| SWT.OK);
					}
				} catch (Exception ex) {
					message(getShell(), "Save Error.", ex.getMessage(),
							SWT.ICON_ERROR | SWT.OK);
					log.error(ex.getMessage(), ex);
				}
			}
		});
		saveButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		saveButton.setText("Save");
		saveButton.setBounds(128, 600, 75, 30);

		final Button saveButton_1 = new Button(shell, SWT.NONE);
		saveButton_1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getShell().close();
			}
		});
		saveButton_1.setImage(SWTResourceManager.getImage(ProductAppNew.class,
				"/img/Refresh.png"));
		saveButton_1.setBounds(209, 600, 80, 30);
		saveButton_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));
		saveButton_1.setText("Reset");

		text_7 = new Text(composite, SWT.BORDER);
		text_7.setVisible(false);
		text_7.setBounds(709, 355, 172, 30);
		text_7.setToolTipText("prod_weight");
		text_7.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));

		final Label categoryLabel_6 = new Label(composite, SWT.NONE);
		categoryLabel_6.setVisible(false);
		categoryLabel_6.setBounds(590, 358, 65, 20);
		categoryLabel_6.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		categoryLabel_6.setText("Weight");

		combo_1 = new Combo(composite, SWT.NONE);
		combo_1.setVisible(false);
		combo_1.setVisibleItemCount(6);
		combo_1.setToolTipText("prod_weightuom");
		combo_1.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		combo_1.setBounds(887, 355, 95, 25);
		combo_1.add(Product.UOM_ML);
		combo_1.add(Product.UOM_L);
		combo_1.add(Product.UOM_GM);
		combo_1.add(Product.UOM_KG);
		combo_1.select(0);
		//
		buildStandardMenu(getShell(), getParams(),
				InventoryAppCtrl.INVENTORY_CTRL, InventoryAppCtrl.INVENTORY_ENQ);
		populateCombo(combo);

		text_8 = new Text(composite, SWT.BORDER);
		text_8.setBounds(129, 183, 172, 30);
		text_8.setToolTipText("prod_color");
		text_8.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		categoryLabel_1_1 = new Label(composite, SWT.NONE);
		categoryLabel_1_1.setBounds(10, 186, 65, 20);
		categoryLabel_1_1.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		categoryLabel_1_1.setText("Color");

		text_9 = new Text(composite, SWT.BORDER);
		text_9.setBounds(129, 219, 172, 30);
		text_9.setToolTipText("prod_invoiceno");
		text_9.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		text_10 = new Text(composite, SWT.BORDER);
		text_10.setBounds(129, 255, 172, 30);
		text_10.setToolTipText("prod_cost");
		text_10.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont(
				"Segoe UI", 12, SWT.NORMAL));

		categoryLabel_1_2 = new Label(composite, SWT.NONE);
		categoryLabel_1_2.setBounds(10, 222, 75, 20);
		categoryLabel_1_2.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		categoryLabel_1_2.setText("Invoice No");

		categoryLabel_1_3 = new Label(composite, SWT.NONE);
		categoryLabel_1_3.setBounds(10, 258, 65, 20);
		categoryLabel_1_3.setFont(org.eclipse.wb.swt.SWTResourceManager
				.getFont("Segoe UI", 12, SWT.NORMAL));
		categoryLabel_1_3.setText("Cost");
		composite.setTabList(new Control[] { combo, text, text_2, text_8,
				text_9, text_10, text_3, text_4, text_5, text_6 });
	}

	public static List<String> validateForm(Product product) throws Exception {
		List<String> errors = new ArrayList<String>();

		if (StringUtils.isEmpty(product.getName())) {
			errors.add("Name cannot be empty.");
		}
		if (StringUtils.isEmpty(product.getSku())) {
			errors.add("SKU cannot be empty.");
		}
		if (product.getDiscount() == null) {
			errors.add("Discount cannot be empty.");
		}
		if (StringUtils.isEmpty(product.getWeightuom())) {
			errors.add("Weight UOM cannot be empty.");
		}
		if (product.getPrice() == null) {
			errors.add("Price cannot be empty.");
		}
		if (product.getCost() == null) {
			errors.add("Cost cannot be empty.");
		}
		if (product.getQuantity() == null) {
			errors.add("Quantity cannot be empty.");
		}

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		// List<Product> products = new ArrayList<Product>();
		// Criteria cris = session.createCriteria(ProductModel.class).add(
		// Expression.eq(Product.FLD_NAME,
		// product.getName())).add(Expression.eq(Product.FLD_STATUS,
		// AppConstant.STATUS_ACTIVE));
		// if (product.getId() != null) {
		// cris.add(Expression.ne(Product.FLD_ID, product.getId()));
		// }
		// products = cris.list();
		// if (products != null && !products.isEmpty()) {
		// errors.add("Duplicate product name. Please use another name.");
		// }

		List<Product> products = new ArrayList<Product>();
		Criteria cris = session
				.createCriteria(ProductModel.class)
				.add(Expression.eq(Product.FLD_SKU, product.getSku()))
				.add(Expression.eq(Product.FLD_STATUS,
						AppConstant.STATUS_ACTIVE));
		if (product.getId() != null) {
			cris.add(Expression.ne(Product.FLD_ID, product.getId()));
		}
		products = cris.list();
		if (products != null && !products.isEmpty()) {
			errors.add("Duplicate product SKU. Please use another SKU.");
		}

		if (product.getCategory() == null) {
			errors.add("Category cannot be empty.");
		}

		return errors;
	}

	private int doAdd(Product product) throws Exception {
		int rowCount = 0;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		try {
			session.beginTransaction();

			session.save(product);
			rowCount++;
			log.debug(product.getClass().getSimpleName() + " : "
					+ product.getValues().toString());

			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			log.error(e.getMessage(), e);
			throw e;
		}
		return rowCount;
	}

	private void populateCombo(Combo combo) {
		try {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();
			List<Category> categories = session
					.createCriteria(CategoryModel.class)
					.add(Restrictions.eq(Category.FLD_TYPE,
							Category.TYPE_PRODUCT))
					.add(Restrictions.eq(Category.FLD_STATUS,
							AppConstant.STATUS_ACTIVE)).list();
			if (categories != null && !categories.isEmpty()) {
				for (Iterator<Category> iter = categories.iterator(); iter
						.hasNext();) {
					Category category = iter.next();
					combo.add(category.getName());
					combo.setData(category.getName(), category);
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

	public Shell getShell() {
		return shell;
	}

	public static void logProduct(Product product, Map<String, Object> params,
			String actionname, Transaction transaction, Double xquantity) {

		Session session = HibernateUtil.getSessionFactory().openSession();

		Logger log = Logger.getLogger("Log.Product");
		try {
			session.beginTransaction();

			if (product != null) {
				ProductLog plog = new ProductLogModel();

				plog.copyProduct(product);
				plog.setStatus(AppConstant.STATUS_ACTIVE);
				plog.setActionname(actionname);

				if (xquantity == null) {
					plog.setXquantity(0.0);
				} else {
					plog.setXquantity(xquantity);
				}

				List<ProductLog> plogs = session
						.createCriteria(ProductLogModel.class)
						.add(Expression.eq(ProductLog.FLD_PRODUCT, product))
						.addOrder(Order.desc(ProductLog.FLD_VERSION))
						.setMaxResults(1).list();
				if (plogs != null && !plogs.isEmpty()) {
					plog.setVersion(plogs.get(0).getVersion() + 1);
				} else {
					plog.setVersion(1);
				}

				if (params.get(AppConstant.USER) != null) {
					User user = (User) params.get(AppConstant.USER);
					Employee employee = user.getEmployee();

					Date today = new Date();
					plog.setCrtby(employee.getId());
					plog.setCrtdate(today);
					plog.setUpdby(employee.getId());
					plog.setUpddate(today);
				}

				if (transaction != null) {
					plog.setTransaction(transaction);
				}

				session.save(plog);

			}

			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
			log.error("Unable to log product.", e);
		} finally {
			session.close();
		}
	}
}
